home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
PET
/
S-Super PET
/
(s)t2.d64
/
PERIODOGRAM.FTN
< prev
next >
Wrap
Text File
|
2009-01-18
|
8KB
|
304 lines
* Program Periodogram.ftn
*
* This program was typed from the book:
*
* FOURIER ANALYSIS OF TIME SERIES: AN INTRODUCTION
* by Peter Bloomfield
* John Wiley & Sons, 1976
*
* This program computes the discrete Fourier transform
* of a series, and the periodogram.
*
*
real x(1024) , y(1024)
character fnamein,realpartfile,imagpartfile,periodogramfile
maxsize=1024
do 10 i = 1 , maxsize
x(i) = 0.0
y(i) = 0.0
10 continue
write(6,1)
1 format("1 Enter input filename (up to 16 characters)")
read, fnamein
print, "Output file name for the periodogram"
read, periodogramfile
call datin (x , n , start , step , 7 , fnamein)
if n .gt. maxsize
print,"Number of data points is ",n," which exceeds maximum size"
stop
endif
call detrnd( x, n, 0 )
np2 = 1
20 np2 = np2*2
if (np2 .lt. n) go to 20
inv = 0
call ft01a (x , y , np2 , inv)
if (inv .eq. 0) go to 30
write(6,7)
7 format("0 TROUBLE IN ft01a -- np2 OUT OF RANGE")
stop
30 continue
npgm = np2/2 + 1
con = (2.0*float(np2)/float(n))**2
do 40 i = 1 , npgm
40 x(i) = (x(i)**2 + y(i)**2)*con
call datout (x , npgm , 0.0 , 1.0 , 9 , periodogramfile)
stop
end
subroutine datin ( x , n , start , step , m , fname)
*
* This subroutine is used to input a series of values
* (in run time format) and some associated quantities
* (in fixed format). The first four data records are -
*
* 1 A header record (72 bytes)
* 2 Value of n (i5)
* 3 The data format (72 bytes)
* 4 Start and step (2f10.5)
*
* Parameters are -
*
* Name Type Value
* On Entry On Return
*
* x Real array Not used The series
*
* n Integer Series length Unchanged
*
* start Real Not used Time value at the
* first data point
*
* step Real Not used Time increment
* between data points
*
* m Integer Logical unit number Unchanged
*
* fname Character input file name Unchanged
*
real x(1024)
character head , form , fname
open(unit=m,file=fname,access="sequential",recl=80)
read(m,1) head,n,form,start,step
1 format(a72/i5/a72/2f10.5)
write(6,2) head,n,form,start,step
2 format("0The data header reads -"/1x,a72/
& " The series length is",i6/
& " The data format is -"/1x,a72/
& " time origin is",f11.5,
& ", time increment is",f11.5)
read(m,form) (x(i),i=1,n)
close(unit=m)
return
end
subroutine detrnd (x , n , k)
*
* This subroutine computes and subtracts from the
* series x either the series mean or the least squares
* straight line. Note that these are the least squares
* polynomials of degree 0 and 1, respectively.
* Parameters are -
*
* Name Type Value
* On Entry On Return
*
* x Real array The series Detrended series
*
* n Integer Series length Unchanged
*
* k Integer Degree of polynomial Unchanged
* to be fitted
*
real x(n)
sumx = 0.0
do 20 i = 1 , n
sumx = sumx + x(i)
20 continue
xbar = sumx/float(n)
do 30 i = 1 , n
x(i) = x(i) -xbar
30 continue
if (k .le. 0) return
tbar = float(n+1)/2.0
fn = n
sumtt = fn*(fn*fn-1.0)/12.0
sumtx = 0
do 40 i = 1 , n
sumtx = sumtx + x(i)*(float(i)-tbar)
40 continue
beta = sumtx/sumtt
do 50 i = 1 , n
x(i) = x(i) - beta*(float(i)-tbar)
50 continue
return
end
subroutine datout (x , n , start , step , m , fname)
*
* This subroutine outputs the series x in the format
* expected by subroutine datin. The header record is
* blank except for sequencing. Parameters are -
*
* Name Type Value (none are changed)
*
* x Real Array The series
*
* n Integer Series length
*
* start Real Time origin
*
* step Real Time increment
*
* m Integer Logical unit number
*
* fname Character Output file name
*
real x(n),z(4)
character fname
open(unit=m,file=fname,access="sequential",recl=80)
do 7 i = 1 , 4
7 z(i) = 0.0
k = 1
write(m,1) fname , k
1 format(1x,a74,i5)
k = 2
write(m,2) n,k
2 format(i5,70x,i5)
k = 3
write(m,3) k
3 format(" (5e15.8)",66x,i5)
k = 4
write(m,4) start,step,k
4 format(2f10.5,55x,i5)
l = 5
ihi = 0
10 ilo = ihi + 1
ihi = ihi + l
k = k + 1
if (ihi .gt. n) go to 20
write(m,5) (x(i),i=ilo,ihi),k
5 format(5e15.8,i5)
go to 10
20 if (ilo .gt. n) go to 30
lim = ihi - n
write(m,5) (x(i),i=ilo,n),(z(i),i=1,lim),k
30 close(unit=m)
return
end
subroutine ft01a (xr,xi,n,inv)
*
* This subroutine implements the Sande-Tukey radix-2
* Fast Fourier Transform. Either the direct or
* the inverse transform may be computed. Parameters are
*
* Name Type Value
* On Entry On Return
*
* xr real array real part of the real part of the
* series transform
*
* xi real array imaginary part of imaginary part
* the series of the transform
*
* n integer the series length unchanged
*
* inv integer 0 for direct transform inv is set to
* 1 for inverse transform -1 to indicate
* error return
*
* The direct transform is -
*
* n
* (1/n) sum x(t)*exp(-2*pi*i*(t-1)*(j-1)/n), j = 1 to n
* t=1
*
* The inverse transform is -
*
* n
* sum x(t)*exp( 2*pi*i*(t-1)*(j-1)/n), j = 1 to n
* t=1
*
real xr(n),xi(n),ur(15),ui(15)
ur(1) = 0.0
ui(1) = 1.0
do 110 i = 2 , 15
ur(i) = sqrt((1.0+ur(i-1))/2.0)
110 ui(i) = ui(i-1)/(2.0*ur(i))
120 if (n .gt. 0 .and. n .le. 2**14) go to 130
inv = -1
return
130 n0 = 1
ii = 0
140 n0 = n0 + n0
ii = ii + 1
if (n0 .lt. n) go to 140
i1 = n0/2
i3 = 1
i0 = ii
do 260 i4 = 1 , ii
do 250 k = 1, i1
wr = 1.0
wi = 0.0
kk = k - 1
do 230 i = 1 , i0
if (kk .eq. 0) go to 240
if (mod(kk,2) .eq. 0) go to 230
j0 = i0 - i
ws = wr*ur(j0) - wi*ui(j0)
wi = wr*ui(j0) + wi*ur(j0)
wr = ws
230 kk = kk/2
240 if ( inv .eq. 0 ) wi = -wi
l = k
do 250 j = 1 , i3
l1 = l + i1
zr = xr(l) + xr(l1)
zi = xi(l) + xi(l1)
z = wr*(xr(l)-xr(l1))-wi*(xi(l)-xi(l1))
xi(l1) = wr*(xi(l)-xi(l1))+wi*(xr(l)-xr(l1))
xr(l1) = z
xr(l) = zr
xi(l) = zi
250 l = l1 + i1
i0 = i0 - 1
i3 = i3 + i3
260 i1 = i1/2
um = 1.0
if ( inv .eq. 0 ) um = 1.0/float(n0)
do 310 j = 1 , n0
k = 0
j1 = j - 1
do 320 i = 1 , ii
k = 2*k + mod(j1,2)
320 j1 = j1/2
k = k + 1
if ( k .lt. j ) go to 310
zr = xr(j)
zi = xi(j)
xr(j) = xr(k)*um
xi(j) = xi(k)*um
xr(k) = zr*um
xi(k) = zi*um
310 continue
return
end